package com.ionehe.group.common.uaa.ex.domain.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.google.common.base.Throwables;
import com.ionehe.group.common.io.Response;
import com.ionehe.group.common.uaa.ex.model.UaaManageInfo;
import com.ionehe.group.common.user.c.sdk.uaa.utils.JwtTokenUtil;
import com.ionehe.group.common.uaa.ex.dto.AdminUserDetails;
import com.ionehe.group.common.uaa.ex.convert.ManagerInfoConvert;
import com.ionehe.group.common.uaa.ex.dto.FunctionDTO;
import com.ionehe.group.common.uaa.ex.dto.ManageInfoDTO;
import com.ionehe.group.common.uaa.ex.enums.AdminType;
import com.ionehe.group.common.uaa.ex.enums.ErrorMessages;
import com.ionehe.group.common.uaa.ex.exception.BusinessException;
import com.ionehe.group.common.uaa.ex.dao.ManageInfoDao;
import com.ionehe.group.common.uaa.ex.domain.service.AdminCacheReadService;
import com.ionehe.group.common.uaa.ex.domain.service.AdminCacheWriteService;
import com.ionehe.group.common.uaa.ex.domain.service.AdminReadService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * Copyright (c) 2020 ionehe.com
 * Date: 2020/11/29
 * Time: 2:07 下午
 *
 * @author 2020年 <a href="mailto:a@ionehe.com">秀</a>
 */
@Service
@Slf4j
public class AdminReadServiceImpl implements AdminReadService {
    @Autowired
    private AdminCacheReadService adminCacheReadService;
    @Autowired
    private AdminCacheWriteService adminCacheWriteService;
    @Autowired @Lazy
    private JwtTokenUtil jwtTokenUtil;
    @Resource
    private ManageInfoDao manageInfoDao;

    @Autowired(required = false)
    private ManagerInfoConvert managerInfoConvert;

    @Override
    public Response<ManageInfoDTO> getAdminByUsername(String username) {
        log.info("AdminReadService[]getAdminByUsername[]start! username:{}", username);
        try {
            // 缓存获取
            Response<ManageInfoDTO> res = adminCacheReadService.getAdmin(username);
            if (!res.success()) {
                return res;
            }
            ManageInfoDTO admin = res.getData();
            if (admin != null) {
                return res;
            }

            // 数据库获取
            UaaManageInfo manage = new UaaManageInfo();
            manage.setIsDelete(false);
            manage.setAccount(username);
            UaaManageInfo manageInfo = manageInfoDao.selectOne(manage);
            if (manageInfo != null) {
                admin = managerInfoConvert.do2dto(manageInfo);
                adminCacheWriteService.setAdmin(admin);
                return Response.yes(admin);
            }
            return Response.yes(null);
        } catch (Exception e) {
            log.error("AdminReadService[]getAdminByUsername[]error! cause:{}", Throwables.getStackTraceAsString(e));
            return Response.no(ErrorMessages.GET_USER_INFO_FAIL.toString());
        }
    }

    @Override
    public Response<List<FunctionDTO>> getResourceList(String account) {
        // 缓存中获取
        Response<List<FunctionDTO>> resourceListCacheRes = adminCacheReadService.getResourceList(account);
        if (!resourceListCacheRes.success()) {
            throw new BusinessException(resourceListCacheRes.getMessage());
        }
        List<FunctionDTO> resourceList = resourceListCacheRes.getData();

        // 数据库中获取
        if (CollUtil.isEmpty(resourceList)) {
            UaaManageInfo manage = new UaaManageInfo();
            manage.setAccount(account);
            UaaManageInfo admin = manageInfoDao.selectOne(manage);
            if (Objects.isNull(admin)) {
                return Response.no(ErrorMessages.ILLEGAL_OPERATION.getErrCode(), ErrorMessages.ILLEGAL_OPERATION.getErrMsg());
            }
            resourceList = new ArrayList<>();
            switch (AdminType.from(admin.getType())) {
                case DEVELOPER:
                    developerFunction(resourceList);
                    break;
                case PLATFORM_ADMIN:
                    platformFunction(resourceList);
                    break;
                default:
            }
            // 存入缓存中
            adminCacheWriteService.setResourceList(account, resourceList);
        }
        return Response.yes(resourceList);
    }

    @Override
    public Response<UserDetails> loadUserByUsername(String username) {
        log.info("AdminService[]loadUserByUsername[]start! username:{}", username);
        try {
            //获取用户信息
            Response<ManageInfoDTO> adminRes = getAdminByUsername(username);
            if (!adminRes.success()) {
                return Response.no(adminRes.getMessage());
            }
            ManageInfoDTO admin = adminRes.getData();
            // 获取权限
            if (admin != null) {
                List<FunctionDTO> resourceDTOList = getResourceList(admin.getAccount()).getData();
                return Response.yes(new AdminUserDetails(admin, resourceDTOList));
            }

            return Response.yes(null);
        } catch (Exception e) {
            log.error("AdminService[]loadUserByUsername[]error! cause:{}", Throwables.getStackTraceAsString(e));
            return Response.no(ErrorMessages.GET_USER_INFO_FAIL.toString());
        }
    }

    @Override
    public Response<ManageInfoDTO> getAdminByToken(String token) {
        log.info("AdminReadService[]getAdminByToken[]start! token:{}", token);
        String userName = jwtTokenUtil.getUserNameFromToken(token);
        return getAdminByUsername(userName);
    }

    /**********************************              service函数分界线             **************************************/

    private void platformFunction(List<FunctionDTO> functionDTOList) {
        FunctionDTO fun = new FunctionDTO();
        fun.setId(3L);
        fun.setName("客户管理");
        fun.setUrl("/api/uaa/customer/**");
        FunctionDTO fun1 = new FunctionDTO();
        fun1.setId(2L);
        fun1.setName("套餐管理");
        fun1.setUrl("/api/uaa/setMeal/**");
        FunctionDTO fun2 = new FunctionDTO();
        fun2.setId(1L);
        fun2.setName("模块管理");
        fun2.setUrl("/api/uaa/function/**");
        functionDTOList.add(fun);
        functionDTOList.add(fun1);
        functionDTOList.add(fun2);
    }

    private void developerFunction(List<FunctionDTO> functionDTOList) {
        FunctionDTO fun = new FunctionDTO();
        fun.setId(1L);
        fun.setName("模块管理");
        fun.setUrl("/api/uaa/function/**");
        functionDTOList.add(fun);
    }
}
